home *** CD-ROM | disk | FTP | other *** search
/ Cracker's Matrix / Cracker's Matrix (nCite Software).iso / Examples / Data / ckSL_0023.txt < prev   
Text File  |  2003-01-06  |  31KB  |  569 lines

  1. DETTEN CRACKME #12
  2. ******************
  3.  
  4. Cracker:      figugegl
  5. Email:        figugegl_2000@yahoo.de
  6. Date:         21.1.2002
  7. Tools:        Softice, IDA
  8. Level 1-10:   5
  9.  
  10.  
  11.  
  12. This ASM-Crackme has an unusual protection: Out of 15 buttons we have to press the right ones to enter a 10-digit keycode. It took me a while to fully understand what's going on here and how to solve it. The readme-file is a little misleading, Detten says: "Don't try to bruteforce all combinations, too much work! Instead try to figure out the 'holes' in the code". But we do have to bruteforce to get the valid combination.
  13.  
  14. Let┤s have a look at the listing first, especially the part where the buttons are being processed with the WM_COMMAND message. Due to the number of buttons, the listing is quite big:
  15.  
  16. 0040102E 81 7D 0C 10 01 00+    cmp [ebp+arg_4], 110h            ; WM_INITDIALOG
  17. 00401035 75 37                 jnz short loc_40106E
  18. 00401037 C7 05 48 30 40 00+    mov dword_403048, 0              ; loopcounter = 0
  19. 00401041 C7 05 38 30 40 00+    mov dword_403038, 0DEADh         ; a = 0DEADh
  20. 0040104B C7 05 3C 30 40 00+    mov dword_40303C, 0DEADh         ; b = 0DEADh
  21. 00401055 C7 05 40 30 40 00+    mov dword_403040, 42424242h      ; c = 42424242h
  22. 0040105F C7 05 4C 30 40 00+    mov dword_40304C, offset aAnErrorOccured ; ASCII 'An error occured'
  23. 00401069 E9 DE 01 00 00        jmp loc_40124C
  24. 0040106E                   ; ---------------------------------------------------------------------------
  25. 0040106E 83 7D 0C 10           cmp [ebp+arg_4], 10h             ; WM_CLOSE
  26. 00401072 75 0D                 jnz short loc_401081
  27. 00401074 FF 75 08              push [ebp+arg_0]                 ; hWnd
  28. 00401077 E8 32 04 00 00        call j_DestroyWindow             ; DestroyWindow
  29. 0040107C E9 CB 01 00 00        jmp loc_40124C
  30. 00401081                   ; ---------------------------------------------------------------------------
  31. 00401081 81 7D 0C 11 01 00+    cmp [ebp+arg_4], 111h            ; WM_COMMAND
  32. 00401088 0F 85 B5 01 00 00     jnz loc_401243
  33. 0040108E 8B 45 10              mov eax, [ebp+arg_8]
  34. 00401091 8B 55 10              mov edx, [ebp+arg_8]
  35. 00401094 C1 EA 10              shr edx, 10h
  36. 00401097 66 0B D2              or  dx, dx
  37. 0040109A 0F 85 AC 01 00 00     jnz loc_40124C
  38. 004010A0 66 83 F8 65           cmp ax, 65h                      ; Button '1' ?
  39. 004010A4 75 0C                 jnz short loc_4010B2
  40. 004010A6 6A 01                 push 1
  41. 004010A8 E8 F8 01 00 00        call sub_4012A5                  ; call 1
  42. 004010AD E9 40 01 00 00        jmp loc_4011F2
  43. 004010B2                   ; ---------------------------------------------------------------------------
  44. 004010B2 66 83 F8 66           cmp ax, 66h                      ; Button '2' ?
  45. 004010B6 75 0C                 jnz short loc_4010C4
  46. 004010B8 6A 02                 push 2
  47. 004010BA E8 E6 01 00 00        call sub_4012A5                  ; call 1
  48. 004010BF E9 2E 01 00 00        jmp loc_4011F2
  49. 004010C4                   ; ---------------------------------------------------------------------------
  50. 004010C4 66 83 F8 67           cmp ax, 67h                      ; Button '3' ?
  51. 004010C8 75 0C                 jnz short loc_4010D6
  52. 004010CA 6A 03                 push 3
  53. 004010CC E8 D4 01 00 00        call sub_4012A5                  ; call 1
  54. 004010D1 E9 1C 01 00 00        jmp loc_4011F2
  55. 004010D6                   ; ---------------------------------------------------------------------------
  56. 004010D6 66 83 F8 68           cmp ax, 68h                      ; Button '4' ?
  57. 004010DA 75 0C                 jnz short loc_4010E8
  58. 004010DC 6A 04                 push 4
  59. 004010DE E8 C2 01 00 00        call sub_4012A5                  ; call 1
  60. 004010E3 E9 0A 01 00 00        jmp loc_4011F2
  61. 004010E8                   ; ---------------------------------------------------------------------------
  62. 004010E8 66 83 F8 69           cmp ax, 69h                      ; Button '5' ?
  63. 004010EC 75 0C                 jnz short loc_4010FA
  64. 004010EE 6A 05                 push 5
  65. 004010F0 E8 B0 01 00 00        call sub_4012A5                  ; call 1
  66. 004010F5 E9 F8 00 00 00        jmp loc_4011F2
  67. 004010FA                   ; ---------------------------------------------------------------------------
  68. 004010FA 66 83 F8 6A           cmp ax, 6Ah                      ; Button '6' ?
  69. 004010FE 75 0C                 jnz short loc_40110C
  70. 00401100 6A 06                 push 6
  71. 00401102 E8 9E 01 00 00        call sub_4012A5                  ; call 1
  72. 00401107 E9 E6 00 00 00        jmp loc_4011F2
  73. 0040110C                   ; ---------------------------------------------------------------------------
  74. 0040110C 66 83 F8 6B           cmp ax, 6Bh                      ; Button '7' ?
  75. 00401110 75 0C                 jnz short loc_40111E
  76. 00401112 6A 07                 push 7
  77. 00401114 E8 8C 01 00 00        call sub_4012A5                  ; call 1
  78. 00401119 E9 D4 00 00 00        jmp loc_4011F2
  79. 0040111E                   ; ---------------------------------------------------------------------------
  80. 0040111E 66 83 F8 6C           cmp ax, 6Ch                      ; Button '8' ?
  81. 00401122 75 0C                 jnz short loc_401130
  82. 00401124 6A 08                 push 8
  83. 00401126 E8 7A 01 00 00        call sub_4012A5                  ; call 1
  84. 0040112B E9 C2 00 00 00        jmp loc_4011F2
  85. 00401130                   ; ---------------------------------------------------------------------------
  86. 00401130 66 83 F8 6D           cmp ax, 6Dh                      ; Button '9' ?
  87. 00401134 75 0C                 jnz short loc_401142
  88. 00401136 6A 09                 push 9
  89. 00401138 E8 68 01 00 00        call sub_4012A5                  ; call 1
  90. 0040113D E9 B0 00 00 00        jmp loc_4011F2
  91. 00401142                   ; ---------------------------------------------------------------------------
  92. 00401142 66 83 F8 6E           cmp ax, 6Eh                      ; Button '10' ?
  93. 00401146 75 0C                 jnz short loc_401154
  94. 00401148 6A 0A                 push 0Ah
  95. 0040114A E8 56 01 00 00        call sub_4012A5                  ; call 1
  96. 0040114F E9 9E 00 00 00        jmp loc_4011F2
  97. 00401154                   ; ---------------------------------------------------------------------------
  98. 00401154 66 83 F8 6F           cmp ax, 6Fh                      ; Button '11' ?
  99. 00401158 75 0C                 jnz short loc_401166
  100. 0040115A 6A 0B                 push 0Bh
  101. 0040115C E8 44 01 00 00        call sub_4012A5                  ; call 1
  102. 00401161 E9 8C 00 00 00        jmp loc_4011F2
  103. 00401166                   ; ---------------------------------------------------------------------------
  104. 00401166 66 83 F8 70           cmp ax, 70h                      ; Button '12' ?
  105. 0040116A 75 09                 jnz short loc_401175
  106. 0040116C 6A 0C                 push 0Ch
  107. 0040116E E8 32 01 00 00        call sub_4012A5                  ; call 1
  108. 00401173 EB 7D                 jmp short loc_4011F2
  109. 00401175                   ; ---------------------------------------------------------------------------
  110. 00401175 66 83 F8 71           cmp ax, 71h                      ; Button '13' ?
  111. 00401179 75 09                 jnz short loc_401184
  112. 0040117B 6A 0D                 push 0Dh
  113. 0040117D E8 23 01 00 00        call sub_4012A5                  ; call 1
  114. 00401182 EB 6E                 jmp short loc_4011F2
  115. 00401184                   ; ---------------------------------------------------------------------------
  116. 00401184 66 83 F8 72           cmp ax, 72h                      ; Button '14' ?
  117. 00401188 75 09                 jnz short loc_401193
  118. 0040118A 6A 0E                 push 0Eh
  119. 0040118C E8 14 01 00 00        call sub_4012A5                  ; call 1
  120. 00401191 EB 5F                 jmp short loc_4011F2
  121. 00401193                   ; ---------------------------------------------------------------------------
  122. 00401193 66 83 F8 73           cmp ax, 73h                      ; Button '15' ?
  123. 00401197 75 09                 jnz short loc_4011A2
  124. 00401199 6A 0F                 push 0Fh
  125. 0040119B E8 05 01 00 00        call sub_4012A5                  ; call 1
  126. 004011A0 EB 50                 jmp short loc_4011F2
  127.  
  128. Depending on which button has been pressed, a number is pushed on the stack for call 1. What happens there?
  129.  
  130.  
  131. 004012A9 8B 0D 40 30 40 00     mov ecx, dword_403040            ; a
  132. 004012AF 8B 1D 3C 30 40 00     mov ebx, dword_40303C            ; b
  133. 004012B5 A1 38 30 40 00        mov eax, dword_403038            ; c
  134. 004012BA 80 7D 08 01           cmp [ebp+arg_0], 1               ; Button 1
  135. 004012BE 75 10                 jnz short loc_4012D0
  136. 004012C0 81 C1 4B 05 00 00     add ecx, 54Bh                    ; c += 54Bh
  137. 004012C6 0F AF D8              imul ebx, eax                    ; b *= a
  138. 004012C9 33 C1                 xor eax, ecx                     ; a^= c
  139. 004012CB E9 17 01 00 00        jmp loc_4013E7
  140. 004012D0                   ; ---------------------------------------------------------------------------
  141. 004012D0 80 7D 08 02           cmp [ebp+arg_0], 2               ; Button 2
  142. 004012D4 75 12                 jnz short loc_4012E8
  143. 004012D6 81 E9 33 02 00 00     sub ecx, 233h                    ; c -= 233h
  144. 004012DC 6B DB 14              imul ebx, 14h                    ; b *= 14h
  145. 004012DF 03 C8                 add ecx, eax                     ; c += a
  146. 004012E1 23 D8                 and ebx, eax                     ; b &= a
  147. 004012E3 E9 FF 00 00 00        jmp loc_4013E7
  148. 004012E8                   ; ---------------------------------------------------------------------------
  149. 004012E8 80 7D 08 03           cmp [ebp+arg_0], 3               ; Button 3
  150. 004012EC 75 0F                 jnz short loc_4012FD
  151. 004012EE 05 82 05 00 00        add eax, 582h                    ; a += 582h
  152. 004012F3 6B C9 16              imul ecx, 16h                    ; c *= 16h
  153. 004012F6 33 D8                 xor ebx, eax                     ; b ^= a
  154. 004012F8 E9 EA 00 00 00        jmp loc_4013E7
  155. 004012FD                   ; ---------------------------------------------------------------------------
  156. 004012FD 80 7D 08 04           cmp [ebp+arg_0], 4               ; Button 4
  157. 00401301 75 0F                 jnz short loc_401312
  158. 00401303 23 C3                 and eax, ebx                     ; a &= b
  159. 00401305 81 EB 22 12 11 00     sub ebx, 111222h                 ; b -= 111222h
  160. 0040130B 33 C8                 xor ecx, eax                     ; c ^= a
  161. 0040130D E9 D5 00 00 00        jmp loc_4013E7
  162. 00401312                   ; ---------------------------------------------------------------------------
  163. 00401312 80 7D 08 05           cmp [ebp+arg_0], 5               ; Button 5
  164. 00401316 75 0C                 jnz short loc_401324
  165. 00401318 99                    cdq
  166. 00401319 F7 F9                 idiv ecx                         ; a /= c, division rest --> (r)
  167. 0040131B 2B DA                 sub ebx, edx                     ; b -= r
  168. 0040131D 03 C1                 add eax, ecx                     ; a += c
  169. 0040131F E9 C3 00 00 00        jmp loc_4013E7
  170. 00401324                   ; ---------------------------------------------------------------------------
  171. 00401324 80 7D 08 06           cmp [ebp+arg_0], 6               ; Button 6
  172. 00401328 75 0F                 jnz short loc_401339
  173. 0040132A 33 C1                 xor eax, ecx                     ; a ^= c
  174. 0040132C 23 D8                 and ebx, eax                     ; b &= a
  175. 0040132E 81 C1 79 68 54 00     add ecx, 546879h                 ; c += 546879h
  176. 00401334 E9 AE 00 00 00        jmp loc_4013E7
  177. 00401339                   ; ---------------------------------------------------------------------------
  178. 00401339 80 7D 08 07           cmp [ebp+arg_0], 7               ; Button 7
  179. 0040133D 75 12                 jnz short loc_401351
  180. 0040133F 81 E9 F5 5F 02 00     sub ecx, 25FF5h                  ; c -= 25FF5h
  181. 00401345 33 D9                 xor ebx, ecx                     ; b ^= c
  182. 00401347 05 00 10 40 00        add eax, 401000h                 ; a += 401000h
  183. 0040134C E9 96 00 00 00        jmp loc_4013E7
  184. 00401351                   ; ---------------------------------------------------------------------------
  185. 00401351 80 7D 08 08           cmp [ebp+arg_0], 8               ; Button 8
  186. 00401355 75 10                 jnz short loc_401367
  187. 00401357 33 C1                 xor eax, ecx                     ; a ^= c
  188. 00401359 6B DB 14              imul ebx, 14h                    ; b *= 14h
  189. 0040135C 81 C1 89 25 01 00     add ecx, 12589h                  ; c += 12589h
  190. 00401362 E9 80 00 00 00        jmp loc_4013E7
  191. 00401367                   ; ---------------------------------------------------------------------------
  192. 00401367 80 7D 08 09           cmp [ebp+arg_0], 9               ; Button 9
  193. 0040136B 75 0B                 jnz short loc_401378
  194. 0040136D 2D 87 21 54 00        sub eax, 542187h                 ; a -= 542187h
  195. 00401372 2B D8                 sub ebx, eax                     ; b -= a
  196. 00401374 33 C8                 xor ecx, eax                     ; c ^= a
  197. 00401376 EB 6F                 jmp short loc_4013E7
  198. 00401378                   ; ---------------------------------------------------------------------------
  199. 00401378 80 7D 08 0A           cmp [ebp+arg_0], 0Ah             ; Button 10
  200. 0040137C 75 0C                 jnz short loc_40138A
  201. 0040137E 99                    cdq
  202. 0040137F F7 FB                 idiv ebx                         ; a /= b, division rest --> (r)
  203. 00401381 03 DA                 add ebx, edx                     ; b += r
  204. 00401383 0F AF C2              imul eax, edx                    ; a *= r
  205. 00401386 33 CA                 xor ecx, edx                     ; c ^= r
  206. 00401388 EB 5D                 jmp short loc_4013E7
  207. 0040138A                   ; ---------------------------------------------------------------------------
  208. 0040138A 80 7D 08 0B           cmp [ebp+arg_0], 0Bh             ; Button 11
  209. 0040138E 75 13                 jnz short loc_4013A3
  210. 00401390 81 C3 FE 34 12 00     add ebx, 1234FEh                 ; b += 1234FEh
  211. 00401396 81 C1 DE 45 23 00     add ecx, 2345DEh                 ; c += 2345DEh
  212. 0040139C 05 9B 43 A4 9C        add eax, 9CA4439Bh               ; a += 9CA4439Bh
  213. 004013A1 EB 44                 jmp short loc_4013E7
  214. 004013A3                   ; ---------------------------------------------------------------------------
  215. 004013A3 80 7D 08 0C           cmp [ebp+arg_0], 0Ch             ; Button 12
  216. 004013A7 75 09                 jnz short loc_4013B2
  217. 004013A9 33 C3                 xor eax, ebx                     ; a ^= b
  218. 004013AB 2B D9                 sub ebx, ecx                     ; b -= c
  219. 004013AD 6B C9 12              imul ecx, 12h                    ; c *= 12h
  220. 004013B0 EB 35                 jmp short loc_4013E7
  221. 004013B2                   ; ---------------------------------------------------------------------------
  222. 004013B2 80 7D 08 0D           cmp [ebp+arg_0], 0Dh             ; Button 13
  223. 004013B6 75 10                 jnz short loc_4013C8
  224. 004013B8 25 78 56 34 12        and eax, 12345678h               ; a &= 12345678h
  225. 004013BD 81 E9 75 58 06 00     sub ecx, 65875h                  ; c -= 65875h
  226. 004013C3 0F AF D9              imul ebx, ecx                    ; b *= c
  227. 004013C6 EB 1F                 jmp short loc_4013E7
  228. 004013C8                   ; ---------------------------------------------------------------------------
  229. 004013C8 80 7D 08 0E           cmp [ebp+arg_0], 0Eh             ; Button 14
  230. 004013CC 75 0D                 jnz short loc_4013DB
  231. 004013CE 35 55 55 05 00        xor eax, 55555h                  ; a ^= 55555h
  232. 004013D3 81 EB 51 73 58 00     sub ebx, 587351h                 ; b -= 587351h
  233. 004013D9 EB 0C                 jmp short loc_4013E7
  234. 004013DB                   ; ---------------------------------------------------------------------------
  235. 004013DB 80 7D 08 0F           cmp [ebp+arg_0], 0Fh             ; Button 15
  236. 004013DF 75 06                 jnz short loc_4013E7
  237. 004013E1 03 C3                 add eax, ebx                     ; a += b
  238. 004013E3 03 D9                 add ebx, ecx                     ; b += c
  239. 004013E5 03 C8                 add ecx, eax                     ; c += a
  240. 004013E7                   
  241. 004013E7 FF 05 44 30 40 00     inc dword_403044                 ; keycounter++
  242. 004013ED A3 38 30 40 00        mov dword_403038, eax            ; save a
  243. 004013F2 89 1D 3C 30 40 00     mov dword_40303C, ebx            ; save b
  244. 004013F8 89 0D 40 30 40 00     mov dword_403040, ecx            ; save c
  245.  
  246.  
  247. For every button pressed there are some calculations with the three variables a, b and c. They are saved and a counter is incremented. Back to the main program:
  248.  
  249.  
  250. 004011A2 66 83 F8 01           cmp ax, 1                        ; Button "ABOUT"
  251. 004011A6 75 1C                 jnz short loc_4011C4
  252. 004011A8 6A 00                 push 0
  253. 004011AA 68 55 12 40 00        push offset sub_401255           ; DlgProc = CRACKME1.00401255
  254. 004011AF FF 75 08              push [ebp+arg_0]                 ; hOwner
  255. 004011B2 68 BC 02 00 00        push 2BCh                        ; pTemplate = 2BC
  256. 004011B7 FF 35 28 30 40 00     push dword_403028                ; hInst = NULL
  257. 004011BD E8 F2 02 00 00        call j_DialogBoxParamA           ; DialogBoxParamA
  258. 004011C2 EB 2E                 jmp short loc_4011F2
  259. 004011C4                   ; ---------------------------------------------------------------------------
  260. 004011C4 66 83 F8 02           cmp ax, 2                        ; Button "CLEAR"
  261. 004011C8 75 28                 jnz short loc_4011F2
  262. 004011CA C7 05 38 30 40 00+    mov dword_403038, 0DEADh         ; a = 0DEADh
  263. 004011D4 C7 05 3C 30 40 00+    mov dword_40303C, 0DEADh         ; b = 0DEADh
  264. 004011DE C7 05 40 30 40 00+    mov dword_403040, 42424242h      ; c = 42424242h
  265. 004011E8 C7 05 44 30 40 00+    mov dword_403044, 0              ; keycounter = 0
  266.  
  267. This section is pretty much self explanatory: when we press the About-button, the program shows the About box, and when we press the Clear-button, the three variables a, b, c and the loopcounter are reset. We're getting closer to the heart of the protection now:
  268.  
  269. 004011F2 83 3D 48 30 40 00+    cmp dword_403048, 3              ; loopcounter >= 3 ?
  270. 004011F9 73 2D                 jnb short loc_401228             ; no, jump
  271. 004011FB 83 3D 44 30 40 00+    cmp dword_403044, 0Ah            ; keycounter == 10 ?
  272. 00401202 75 3D                 jnz short loc_401241             ; no, jump
  273. 00401204 E8 43 02 00 00        call sub_40144C                  ; yes, call 2
  274. 00401209 68 00 30 40 00        push offset aAnErrorOccured      ; ASCII 'An error occured'
  275. 0040120E FF 75 08              push [ebp+arg_0]                 ; hWnd
  276. 00401211 E8 ED 01 00 00        call sub_401403                  ; call 3
  277. 00401216 C7 05 44 30 40 00+    mov dword_403044, 0              ; keycounter = 0
  278. 00401220 FF 05 48 30 40 00     inc dword_403048                 ; loopcounter++
  279. 00401226 EB 19                 jmp short loc_401241
  280. 00401228                   ; ---------------------------------------------------------------------------
  281. 00401228 68 11 30 40 00        push offset aTryingToBrutef      ; Text = 'Trying to bruteforce?'
  282. 0040122D 6A 03                 push 3                           ; ControlID = 3
  283. 0040122F FF 75 08              push [ebp+arg_0]                 ; hWnd
  284. 00401232 E8 89 02 00 00        call j_SetDlgItemTextA           ; SetDlgItemTextA
  285. 00401237 C7 05 44 30 40 00+    mov dword_403044, 0              ; keycounter = 0
  286. 00401241 EB 09                 jmp short loc_40124C
  287.  
  288. If the loopcounter is three, the program shows a nice message: 'Trying to bruteforce?' - I love Detten's humor :-)) We see that the length of the serial is 10, otherwise we jump over call 2 and 3. Call 2 is interesting:
  289.  
  290. 0040144C 50                    push eax
  291. 0040144D 68 50 30 40 00        push offset unk_403050           ; new access protection attributes
  292. 00401452 6A 04                 push 4                           ; NewProtect = PAGE_READWRITE
  293. 00401454 68 F4 01 00 00        push 1F4h                        ; Size = 1F4 (500.)
  294. 00401459 68 07 14 40 00        push offset loc_401407           ; Address = CRACKME1.00401407
  295. 0040145E E8 6F 00 00 00        call j_VirtualProtect            ; protect address 401407
  296. 00401463 A1 38 30 40 00        mov eax, dword_403038
  297. 00401468 31 05 07 14 40 00     xor dword ptr ds:loc_401407, eax ; d ^= a
  298. 0040146E 80 3D 07 14 40 00+    cmp byte ptr ds:loc_401407, 52h  ; d[0] == 52h ?
  299. 00401475 75 18                 jnz short loc_40148F             ; no: decryption failed, jump
  300. 00401477 A1 3C 30 40 00        mov eax, dword_40303C
  301. 0040147C 31 05 3B 14 40 00     xor ds:dword_40143B, eax         ; yes: e ^= b
  302. 00401482 A1 40 30 40 00        mov eax, dword_403040
  303. 00401487 31 05 3F 14 40 00     xor ds:dword_40143F, eax         ; f ^= c
  304. 0040148D EB 06                 jmp short loc_401495             ; jump
  305. 0040148F 31 05 07 14 40 00     xor dword ptr ds:loc_401407, eax ; restore d in case decryption has failed
  306. 00401495 68 50 30 40 00        push offset unk_403050           ; restore access protection attributes
  307. 0040149A 6A 10                 push 10h                         ; NewProtect = PAGE_EXECUTE
  308. 0040149C 68 F4 01 00 00        push 1F4h                        ; Size = 1F4 (500.)
  309. 004014A1 68 07 14 40 00        push offset loc_401407           ; Address = CRACKME1.00401407
  310. 004014A6 E8 27 00 00 00        call j_VirtualProtect            ; protect address 401407
  311. 004014AB 58                    pop eax
  312. 004014AC C3                    retn
  313.  
  314. Here we have some SMC - that's the whole trick. The three variables a, b and c are xored with the dwords at address 401407, 40143B and 40143F respectively. These addresses are in call 3. The first byte at address 401407 must be 52h. This is a security measure to check that everything has been well decrypted. Otherwise there might have been produced some garbage instructions that terminate the crackme with an error. Let's have a look at call 3:
  315.  
  316. 00401403 55                  push  ebp
  317. 00401404 8B EC               mov   ebp, esp
  318. 00401406 50                  push  eax
  319. 00401407 EB 3F               jmp   short locret_401448          ; first dword to be decrypted --> (d)
  320. 00401409 90                  nop                                ;
  321. 0040140A 90                  nop                                ;
  322. 0040140B 42                  inc   edx
  323. 0040140C 8B 02               mov   eax, [edx]                   ; decrypt string
  324. 0040140E 35 0D 43 00 01      xor   eax, 100430Dh
  325. 00401413 89 02               mov   [edx], eax
  326. 00401415 83 C2 04            add   edx, 4
  327. 00401418 8B 02               mov   eax, [edx]
  328. 0040141A 35 01 4F 15 52      xor   eax, 52154F01h
  329. 0040141F 89 02               mov   [edx], eax
  330. 00401421 83 C2 04            add   edx, 4
  331. 00401424 8B 02               mov   eax, [edx]
  332. 00401426 35 0E 0D 17 10      xor   eax, 10170D0Eh
  333. 0040142B 89 02               mov   [edx], eax
  334. 0040142D 83 C2 04            add   edx, 4
  335. 00401430 8B 02               mov   eax, [edx]
  336. 00401432 35 16 45 45 00      xor   eax, 454516h
  337. 00401437 89 02               mov   [edx], eax
  338. 00401439 5A                  pop   edx
  339. 0040143A 58                  pop   eax
  340. 0040143A                   ; ---------------------------------------------------------------------------
  341. 0040143B 04 66 E7 BB       dword_40143B dd 0BBE76604h           ; second dword to be decrypted --> (e)
  342. 0040143F 4D BD 08 8B       dword_40143F dd 8B08BD4Dh            ; third dword to be decrypted --> (f)
  343. 00401443                   ; ---------------------------------------------------------------------------
  344. 00401443 E8 78 00 00 00      call  j_SetDlgItemTextA            ; seems to be the success message
  345. 00401448 C9                  leave
  346. 00401449 C2 08 00            retn  8
  347.  
  348. Well, this seems to be the success routine - the api function "SetDlgItemTextA" is very suspicious. We've learned in the call before that the three dwords at adress 401407, 40143B and 40143F are xored with variables, whose values depends on which keys have been pressed. We have to "guess" what instruction are missing in order to show a success message.
  349.  
  350. First of all: Where is the success message? We find two arguments being pushed on the stack before the call:
  351.  
  352. 00401209 68 00 30 40 00        push offset aAnErrorOccured      ; ASCII 'An error occured'
  353. 0040120E FF 75 08              push [ebp+arg_0]                 ; hWnd
  354. 00401211 E8 ED 01 00 00        call sub_401403                  ; call 3
  355.  
  356. Hmm, the string 'An error occured' - my Zen-instinct tells me that this is a fishy thing! We singlestep the routine, jump to address 40140B and change register edx to 403000, the offset of the string mentioned. And I was right, the decrypted string is "ACCESS GRANTED !". Well, that's a beginning. We now know, what should be displayed instead of "NO ACCESS".
  357.  
  358. Fortunately, there's another "SetDlgItemTextA" in the main program, the one that shows the bruteforce message:
  359.  
  360. 00401228 68 11 30 40 00        push offset aTryingToBrutef      ; Text = 'Trying to bruteforce?'
  361. 0040122D 6A 03                 push 3                           ; ControlID = 3
  362. 0040122F FF 75 08              push [ebp+arg_0]                 ; hWnd
  363. 00401232 E8 89 02 00 00        call j_SetDlgItemTextA           ; SetDlgItemTextA
  364.  
  365. All we have to do is change the offset, all the other arguments are the same. The first and last one needed for the API function are being pushed in the main code (see above), we have to adjust call 3 accordingly. We know that byte 401407 has to be 52h, which is a "push edx" instruction. Then there are three bytes left, before the decryption of the string begins. This will only be done properly when register edx is the offset of the string, i.e. 403000. We have to load this into edx, but an ordinary mov edx, 403000 won't fit in three bytes.
  366.  
  367. That's where the pushed arguments are needed. It's a ebp-based subroutine, and therefore we can find the pushed arguments at [ebp+x]. (If you don't know what I'm talking about, read some asm-related tuts. There once was a very good thread covering this topic on woodmanns/fravias board. This tut is already getting too long anyway...). We find the correct argument at [ebp+0C]. Therefore the right instruction is:
  368.  
  369. 00401407  52                 push  edx
  370. 00401408  8B 55 0C           mov   edx, [ebp+C]
  371.  
  372. OK, the first dword is solved. After having decrypted the string, the program needs to pass the three needed arguments on the stack as shown in the example with the "bruteforce" string. We know the offset of the success string is [ebp+C], and pushing this is a three-byte instruction. Then we need to push the controll id, which is a two byte-instruction. Finally we need to push the handle, which has been passed on the stack together with the encrypted string. We find it at [ebp+8], and it's a three-byte instruction. This is 3 + 2 + 3 = 8 bytes = 2 dwords - BINGO!
  373.  
  374. 0040143B  FF 75 0C           push dword ptr [ebp+c]
  375. 0040143E  6A 03              push 3
  376. 00401440  FF 75 08           push dword ptr [ebp+8]
  377.  
  378. We trace this in Softice and adjust the memory accordingly - and it works! Now the main work has been done, we "only" need to bruteforce the right combination. We have:
  379.  
  380.     address    before            after           xor
  381.     ----------------------------------------------------
  382.     401407  EB 3F 90 90  -->  52 8B 55 0C    B9 B4 C5 9C  --> (a)
  383.     40143B  04 66 E7 BB  -->  FF 75 0C 6A    FB 13 EB D1  --> (b)
  384.     40143F  4D BD 08 8B  -->  03 FF 75 08    4E 42 7D 83  --> (c)
  385.  
  386. These are the values of our three variables a, b and c. After xoring them with the corresponding addresses 401407, 40143B and 40143F we get the right opcodes to have the success message displayed. In the messageboard of Dettens page he gives us the first two keys: 79. Otherwise the bruteforcing might take too long. One thing to remember: All calculations take place in registers, thats why all the dwords from memory must be in reverse order (little endian).
  387.  
  388.     Serial: 79DE624C4B
  389.     ******************
  390.  
  391. ---------------------------------------------------------------------------
  392. ---------------------------------------------------------------------------
  393. Here's the source code of my bruteforcer in c (calculation only):
  394.  
  395. void ThreadProc (PVOID pvoid)
  396. {
  397.     char                szSerial[11] = "";
  398.     int                    i, iVarA, iVarB, iVarC, iVarTemp, iSerial[10];
  399.     volatile PPARAMS    pparams;
  400.  
  401.     pparams = (PPARAMS) pvoid;
  402.  
  403.     // bruteforce serial
  404.     for (iSerial[0] = 7; iSerial[0] <= 7; iSerial[0]++)
  405.     {
  406.      for (iSerial[1] = 9; iSerial[1] <= 9; iSerial[1]++)
  407.      {
  408.       for (iSerial[2] = 1; iSerial[2] <= 15; iSerial[2]++)
  409.       {
  410.        for (iSerial[3] = 1; iSerial[3] <= 15; iSerial[3]++)
  411.        {
  412.         for (iSerial[4] = 1; iSerial[4] <= 15; iSerial[4]++)
  413.         {
  414.          for (iSerial[5] = 1; iSerial[5] <= 15; iSerial[5]++)
  415.          {
  416.           for (iSerial[6] = 1; iSerial[6] <= 15; iSerial[6]++)
  417.           {
  418.            for (iSerial[7] = 1; iSerial[7] <= 15; iSerial[7]++)
  419.            {
  420.             for (iSerial[8] = 1; iSerial[8] <= 15; iSerial[8]++)
  421.             {
  422.              for (iSerial[9] = 1; iSerial[9] <= 15; iSerial[9]++)
  423.              {
  424.                 iVarA = 0xDEAD;
  425.                 iVarB = 0xDEAD;
  426.                 iVarC = 0x42424242;
  427.  
  428.                 for (i = 0; i < 10; i++)
  429.                 {
  430.                     switch (iSerial[i])
  431.                     {
  432.                     case 1:
  433.                         iVarC += 0x54B;
  434.                         iVarB *= iVarA;
  435.                         iVarA ^= iVarC;
  436.                         break;
  437.  
  438.                     case 2:
  439.                         iVarC = iVarC - 0x233 + iVarA;
  440.                         iVarB = (iVarB * 0x14) & iVarA;
  441.                         break;
  442.  
  443.                     case 3:
  444.                         iVarA += 0x582;
  445.                         iVarC *= 0x16;
  446.                         iVarB ^= iVarA;
  447.                         break;
  448.  
  449.                     case 4:
  450.                         iVarA &= iVarB;
  451.                         iVarB -= 0x111222;
  452.                         iVarC ^= iVarA;
  453.                         break;
  454.  
  455.                     case 5:
  456.                         if (iVarC != 0)
  457.                         {
  458.                             iVarB -= (iVarA % iVarC);
  459.                             iVarA /= iVarC;
  460.                             iVarA += iVarC;
  461.                         }
  462.                         break;
  463.  
  464.                     case 6:
  465.                         iVarA ^= iVarC;
  466.                         iVarB &= iVarA;
  467.                         iVarC += 0x546879;
  468.                         break;
  469.  
  470.                     case 7:
  471.                         iVarC -= 0x25FF5;
  472.                         iVarB ^= iVarC;
  473.                         iVarA += 0x401000;
  474.                         break;
  475.  
  476.                     case 8:
  477.                         iVarA ^= iVarC;
  478.                         iVarB *= 0x14;
  479.                         iVarC += 0x12589;
  480.                         break;
  481.  
  482.                     case 9:
  483.                         iVarA -= 0x542187;
  484.                         iVarB -= iVarA;
  485.                         iVarC ^= iVarA;
  486.                         break;
  487.  
  488.                     case 10:
  489.                         if (iVarB != 0)
  490.                         {
  491.                             iVarTemp = iVarA % iVarB;
  492.                             iVarA /= iVarB;
  493.                             iVarB += iVarTemp;
  494.                             iVarA *= iVarTemp;
  495.                             iVarC ^= iVarTemp;
  496.                         }
  497.                         break;
  498.  
  499.                     case 11:
  500.                         iVarB += 0x1234FE;
  501.                         iVarC += 0x2345DE;
  502.                         iVarA += 0x9CA4439B;
  503.                         break;
  504.  
  505.                     case 12:
  506.                         iVarA ^= iVarB;
  507.                         iVarB -= iVarC;
  508.                         iVarC *= 0x12;
  509.                         break;
  510.  
  511.                     case 13:
  512.                         iVarA &= 0x12345678;
  513.                         iVarC -= 0x65875;
  514.                         iVarB *= iVarC;
  515.                         break;
  516.  
  517.                     case 14:
  518.                         iVarA ^= 0x55555;
  519.                         iVarB -= 0x587351;
  520.                         break;
  521.  
  522.                     case 15:
  523.                         iVarA += iVarB;
  524.                         iVarB += iVarC;
  525.                         iVarC += iVarA;
  526.                         break;
  527.                     }
  528.                 }
  529.  
  530.                 // stop thread if serial ok
  531.                 if ((iVarA == 0x9CC5B4B9) && (iVarB == 0xD1EB13FB) && (iVarC == 0x837D424E))
  532.                 {
  533.                     for (i = 0; i < 10; i++)
  534.                     {
  535.                         if (iSerial[i] <= 9)
  536.                         {
  537.                             szSerial[i] = iSerial[i] + 0x30;
  538.                         }
  539.                         else
  540.                         {
  541.                             szSerial[i] = iSerial[i] + 0x37;
  542.                         }
  543.                     }
  544.                     SendMessageA (pparams->hWnd, WM_USER, 0, (LPARAM) (LPCTSTR) szSerial);
  545.                     _endthread ();
  546.                     return;
  547.                 }
  548.  
  549.                 // stop thread if stop button pressed
  550.                 if  (!pparams->bContinue)
  551.                 {
  552.                     SendMessageA (pparams->hWnd, WM_USER, 0, (LPARAM) (LPCTSTR) NULL);
  553.                     _endthread ();
  554.                     return;
  555.                 }
  556.              }
  557.             }
  558.            }
  559.           }
  560.          }
  561.         }
  562.        }
  563.       }
  564.      }
  565.     }
  566.     _endthread ();
  567.     return;
  568. }
  569.